package com.google.code.stalkernet.reactor;

import java.io.IOException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;

/**
 * Reactor that handles different kinds of events in a single loop.
 *
 * @author Mikhail Vladimirov
 */
public interface Reactor
{
    /**
     * Register given {@link SelectableChannel} to be monitored by the
     * reactor.
     *
     * @param selectableChannel {@link SelectableChannel} to monitor
     * @param selectableChannelCallback {@link SelectableChannelCallback} to
     *         notify when {@link SelectableChannel} is selected
     * @return {@link SelectionKey} object associated with given
     *         {@link SelectableChannel}
     * @throws IOException if I/O error happened
     */
    public SelectionKey registerSelectableChannel (
        SelectableChannel selectableChannel,
        SelectableChannelCallback selectableChannelCallback)
        throws IOException;

    /**
     * Schedule given {@link Runnable} to be run at given time.
     *
     * @param runnable {@link Runnable} to invoke
     * @param time time to invoke given {@link Runnable} at
     * @return {@link ScheduledTaskHandle} object
     */
    public ScheduledTaskHandle schedule (Runnable runnable, long time);

    /**
     * Invoke given {@link Runnable} in reactor thread.  This is the only
     * method that can be run from thread other than reactor thread.
     *
     * @param runnable {@link Runnable} to invoke
     */
    public void invoke (Runnable runnable);

    /**
     * Shutdown the reactor.
     */
    public void shutdown ();

    /**
     * Receives notifications about {@link SelectableChannel} events.
     */
    public interface SelectableChannelCallback
    {
        /**
         * Called when {@link SelectableChannel} was selected in {@link Reactor}.
         *
         * @param selectionKey SelectionKey object associated with
         *        {@link SelectableChannel} that was selected
         */
        public void selected (SelectionKey selectionKey);
    }

    /**
     * Handle of scheduled reactor task.
     */
    public interface ScheduledTaskHandle
    {
        /**
         * Cancel scheduled task.
         *
         * @return <code>true</code> if task was cancelled, <code>false</code>
         *         if it is to late to cancel task
         */
        public boolean cancel ();
    }
}
